<template>
  <div class="clip-upload-img">
    <div class="img-list">
      <template v-for="(v, i) in imagesUrl" :key="v">
        <div class="img-list_item">
          <div class="img-list_item--info w-full h-full">
            <Image :src="v" width="100%" height="100%" />
          </div>
          <div class="img-list_item--del">
            <Icon
              icon="ant-design:close-circle-filled"
              color="#ff4d4f"
              :size="20"
              @click="handleRemove(i)"
            />
          </div>
        </div>
      </template>
      <Upload
        :accept="fileTypeList.join(',')"
        :action="cropper ? '' : '/api/system/dfs/image_upload'"
        :headers="{
          token: getToken() as string,
          tenantId: getAuthCache(TENANT_ID)
        }"
        :multiple="!cropper"
        :show-upload-list="false"
        :disabled="disabled"
        :max-count="maxNumber"
        :before-upload="beforeUpload"
        @change="upImgChange"
      >
        <div class="upload-button" v-if="imagesUrl.length < maxNumber">
          <PlusOutlined />
          <div class="ant-upload-text">Upload</div>
        </div>
      </Upload>
    </div>

    <ImgCopperModal
      v-if="cropper"
      @register="register"
      @upload-success="handleUploadSuccess"
      @upload-cancel="handleUploadCancel"
      :uploadApi="uploadApi"
      :circled="false"
      :src="sourceValue"
    />
  </div>
</template>

<script setup lang="ts">
  import { ref, unref, watch } from 'vue';
  import { Upload } from 'ant-design-vue';
  import { PlusOutlined } from '@ant-design/icons-vue';
  import { useMessage } from '@/hooks/web/useMessage';
  import { useI18n } from '@/hooks/web/useI18n';
  import ImgCopperModal from '@/components/Cropper/src/ImgCopperModal.vue';
  import { useModal } from '@/components/Modal';
  import { uploadApi } from '@/api/sys/index';
  import { UploadResult } from '@/api/model/baseModel';
  import { buildUUID } from '@/utils/uuid';
  import { getBase64WithFile } from './helper';
  import Icon from '@/components/Icon/src/Icon.vue';
  import { FileItem } from './typing';
  import { Image } from 'ant-design-vue';
  import { getToken, getAuthCache } from '@/utils/auth';
  import { TENANT_ID } from '@/enums/cacheEnum';

  const props = defineProps({
    modelValue: String as PropType<string>,
    // 图片最大多少MB
    maxSize: {
      type: Number as PropType<number>,
      default: 2,
    },
    // 图片可上传数
    maxNumber: {
      type: Number as PropType<number>,
      default: 1,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否需要裁剪
    cropper: {
      type: Boolean,
      default: true,
    },
  });

  const emit = defineEmits(['update:modelValue']);

  watch(
    () => props.modelValue,
    (val: string | string[]) => {
      if (val && Array.isArray(val)) imagesUrl.value = val;
      else if (val) imagesUrl.value = [val];
      else imagesUrl.value = [];
    },
  );

  // 支持jpg、png格式，不超过2M，最多可选择10张图片，。

  const { t } = useI18n();
  const { createMessage } = useMessage();

  // 支持的图片后缀
  const fileTypeList = ref(['.jpg', '.png', '.jpeg']);
  const imagesUrl = ref<string[]>([]);

  const fileList = ref<FileItem[]>([]);

  /** 上传前校验 */
  const beforeUpload = (file: File) => {
    const { type } = file;
    const { maxSize } = props;
    if (!verifyFileFormat(type)) {
      createMessage.error(t('component.upload.acceptUpload', [fileTypeList.value.join(',')]));
      return false;
    }
    // 设置最大值，则判断
    if (maxSize && file.size / 1024 / 1024 >= maxSize) {
      createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
      return false;
    }
    sourceValue.value = file;
    if (props.cropper) {
      openModal();
      return false;
    } else {
      return true;
    }
  };

  // 判断图片格式
  function verifyFileFormat(type: string) {
    const fileType = type.split('/')[1];
    let index = fileTypeList.value.findIndex(
      (str) => str.toUpperCase() === `.` + fileType.toUpperCase(),
    );
    return index !== -1;
  }

  /** 图片裁剪模块相关 */
  const [register, { openModal }] = useModal();
  const sourceValue = ref<File>();
  const handleUploadSuccess = (e: { source: string; data: UploadResult }) => {
    const { data } = e;
    if (imagesUrl.value.length < props.maxNumber) {
      imagesUrl.value.push(data.imagePathBig);
      emit(
        'update:modelValue',
        !props.cropper && props.maxNumber === 1 ? data.imagePathBig : imagesUrl.value,
      );
      const file = sourceValue.value as File;
      const { size, name } = file;
      removeLastFile();
      const commonItem = {
        uuid: buildUUID(),
        file,
        size,
        name,
        percent: 0,
        type: name.split('.').pop(),
      };
      getBase64WithFile(file).then(({ result: thumbUrl }) => {
        fileList.value = [
          ...unref(fileList),
          {
            thumbUrl: thumbUrl,
            ...commonItem,
          },
        ];
        console.log('fileList--->', fileList);
      });

      sourceValue.value = void 0;
    } else {
      createMessage.warning(`最多只能上传${props.maxNumber}张图片，超出的会自动忽略！`);
    }
  };

  const handleRemove = (i: number) => handleUploadCancel(i);

  const handleUploadCancel = (i?: number) => {
    if (i === undefined) {
      imagesUrl.value.splice(imagesUrl.value.length - 1, 1);
      removeLastFile();
    } else {
      imagesUrl.value.splice(i, 1);
      removeLastFile(i);
    }
  };

  function removeLastFile(i?: number) {
    if (i === undefined) {
      fileList.value.splice(fileList.value.length - 1, 1);
    } else {
      fileList.value.splice(i, 1);
    }
  }

  function upImgChange(e) {
    if (props.cropper) return;
    const { file } = e;
    if (file.percent === 100 && file.response && file.response.code === 0) {
      handleUploadSuccess({ source: file.response.data.imagePathBig, data: file.response.data });
    }
  }
</script>

<style scoped lang="less">
  .clip-upload-img {
    .img-list {
      user-select: none;
      display: flex;
      flex-wrap: wrap;

      &_item,
      .upload-button {
        width: 128px;
        height: 128px;
        position: relative;
        padding: 8px;
        border: 1px solid #d9d9d9;
        border-radius: 2px;
        margin: 0 8px 8px 0;
      }

      &_item {
        &--del {
          position: absolute;
          right: 0;
          top: 0;
          cursor: pointer;
          z-index: 9;
          transition: all 0.3s;
        }
      }

      .upload-button {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
        cursor: pointer;
        border-style: dashed;

        .ant-upload-text {
          margin-top: 10px;
        }

        &:hover {
          border-color: #1890ff;
        }
      }
    }
  }
</style>
